//------------------------------------------------------------------------------
//  DisplayDevice.cpp
//  (C) 2009 xoyojank
//------------------------------------------------------------------------------
#include "StdEddy.h"
#include "Graphics/DisplayDevice.h"
#include <ShellNotifyMsg.h>

//------------------------------------------------------------------------------
namespace Eddy
{

// default full screen style
#define WND_STYLE	(WS_POPUP | WS_BORDER | WS_SYSMENU | WS_VISIBLE)
#define WND_CLASS	(L"EddyMainWindow")

//------------------------------------------------------------------------------
DisplayDevice::DisplayDevice()
    : isOpen(false)
    , isWndCreated(false)
    , windowTitle(L"Eddy Rendering Window")
    , hWnd(NULL)
{
    this->hInst = GetModuleHandle(NULL);

    // default window size
    this->windowRect.left = 0;
    this->windowRect.top = 0;
    this->windowRect.right = 480;
    this->windowRect.bottom = 720;
}

//------------------------------------------------------------------------------
DisplayDevice::~DisplayDevice()
{
    assert(!this->IsOpen());
}

//------------------------------------------------------------------------------
bool
DisplayDevice::Open()
{
    assert(!this->IsOpen());

    this->isOpen = true;
    // if there is no window exist, create a new one
    if (NULL == this->hWnd)
    {
        this->isOpen = this->OpenWindow();
    }
    else
    {
        GetClientRect(this->hWnd, &this->windowRect);
    }
    // phone settings
    if (IsLockPhoneStatus())
        MzLeaveLockPhone();
    HideMzTopBar();
    SetScreenAlwaysOn(this->hWnd);

    return this->isOpen;
}

//------------------------------------------------------------------------------
void
DisplayDevice::Close()
{
    assert(this->IsOpen());

    this->CloseWindow();
    // restore phone settings
    SetScreenAutoOff();
    ShowMzTopBar();

    this->isOpen = false;
}

//------------------------------------------------------------------------------
bool
DisplayDevice::OpenWindow()
{
    WNDCLASS wc			= {0};
    wc.style			= CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc		= WinProc;
    wc.hInstance		= this->hInst;
    wc.hbrBackground	= (HBRUSH)GetStockObject(NULL_BRUSH);
    wc.lpszClassName	= WND_CLASS;
    RegisterClass(&wc);
    // adjust window rect
    AdjustWindowRectEx(&this->windowRect, WND_STYLE, FALSE, 0);
    // creat window
    this->hWnd = CreateWindow(WND_CLASS,
                              this->windowTitle.c_str(),
                              WND_STYLE,
                              this->windowRect.left,
                              this->windowRect.top,
                              this->windowRect.right - this->windowRect.left,
                              this->windowRect.bottom - this->windowRect.top,
                              NULL, NULL, this->hInst, NULL);
    if (NULL == this->hWnd)
        return false;

    this->isWndCreated = true;

    return true;
}

//------------------------------------------------------------------------------
void
DisplayDevice::CloseWindow()
{
    if (this->isWndCreated)
    {
        if (NULL != this->hWnd)
            DestroyWindow(this->hWnd);
        UnregisterClass(WND_CLASS, this->hInst);
        this->isWndCreated = false;
    }
    this->hWnd = NULL;
}

//------------------------------------------------------------------------------
LRESULT CALLBACK
DisplayDevice::WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    DisplayDevice* self = DisplayDevice::Instance();
    switch (uMsg)
    {
    case WM_ERASEBKGND:
        return 1;
    case WM_CLOSE:
    {
        self->hWnd = NULL;
        PostQuitMessage(0);
    }
    break;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

//------------------------------------------------------------------------------
void
DisplayDevice::ProcessWindowMessage()
{
    assert(this->IsOpen());

    if (NULL == this->hWnd)
        return;

    MSG msg;
    while (PeekMessage(&msg, this->hWnd, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

}// Eddy